package com.agileai.bpm.interceptor.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;

import com.agileai.bpm.common.BPMConstants;
import com.agileai.bpm.common.VariableInterpreter;
import com.agileai.bpm.domain.define.Activity;
import com.agileai.bpm.domain.running.ActivityInstance;
import com.agileai.bpm.domain.running.ProcessVariableInstance;
import com.agileai.bpm.interceptor.BaseInterceptor;
import com.agileai.bpm.model.DBOperaterType;
import com.agileai.bpm.model.InterceptorModelDocument.InterceptorModel;
import com.agileai.util.DBUtil;
import com.agileai.util.StringUtil;

public class DBOperateInterceptor extends BaseInterceptor{
	private static final Logger loger = Logger.getLogger(DBOperateInterceptor.class);
	
	private String datasourceName = null;
	private String sqlTemplate = null;
	private Connection connection = null;
	
	public DBOperateInterceptor(){
		this.type = BaseInterceptor.Type.DBOperater;
	}
	
	public DBOperateInterceptor(InterceptorModel model,Activity activity){
		this.type = BaseInterceptor.Type.DBOperater;
		this.isSynchronous = model.getSynchronous();
		this.variableCode = model.getVariableCode();
		this.varExpression = model.getVarExpression();
		
		DBOperaterType dbOperaterType = model.getDBOperater();
		this.datasourceName = dbOperaterType.getDataSource();
		this.sqlTemplate = dbOperaterType.getUpdateSQL();
	}
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void doIntercept(ActivityInstance activityInstance) throws SQLException {
		String sql = VariableInterpreter.replaceVariables(this.sqlTemplate, activityInstance);
		loger.info("sql is : " + sql);
		this.connection = getConnection(datasourceName);
		try {
			if (this.isSynchronous){
				List<HashMap> dataSet = DBUtil.getRecords(connection, sql);
				if (dataSet != null){
					for (int i=0;i < dataSet.size();i++){
						HashMap row = dataSet.get(i);
						if (BPMConstants.EmbedVariable.targetUserIds.equals(this.variableCode)
								|| BPMConstants.EmbedVariable.targetUserCodes.equals(this.variableCode)){
							String targetUserCode = (String)row.get(BPMConstants.EmbedVariable.targetUserCodeKey);
							if (!StringUtil.isNullOrEmpty(targetUserCode)){
								activityInstance.getTargetUserCodeList().add(targetUserCode);
							}else{
								String targetUserId = (String)row.get(BPMConstants.EmbedVariable.targetUserIdKey);
								if (!StringUtil.isNullOrEmpty(targetUserId)){
									activityInstance.getTargetUserIdList().add(targetUserId);
								}							
							}
						}else{
							HashMap<String, ProcessVariableInstance> hashMap = activityInstance.getProcessInstance().getVariableInstances(); 
							ProcessVariableInstance processVariableInstance = hashMap.get(variableCode);
							if (processVariableInstance != null){
								String varValue = String.valueOf(row.get(variableCode));
								if (StringUtil.isNullOrEmpty(varValue)){
									varValue = String.valueOf(row.get(variableCode.toUpperCase()));
								}
								processVariableInstance.setValue(varValue);
							}
						}
					}
				}
			}else{
				connection.setAutoCommit(false);
				DBUtil.executeUpdateSql(connection, sql);
				connection.commit();
			}
		} catch (SQLException e) {
			throw e;
		} finally{
			DBUtil.close(connection);			
		}
	}

	protected Connection getConnection(String datasourceName) throws SQLException{
		Connection result = null;
		if (!datasourceName.startsWith("proxool.")){
			datasourceName = "proxool."+datasourceName;
		}
		result = DriverManager.getConnection(datasourceName);;
		return result;
	}
	
	public void handleException(ActivityInstance activityInstance,Exception ex) {
		if (this.connection != null){
			DBUtil.close(connection);
		}
		loger.error(ex.getLocalizedMessage(), ex);
	}
	

	public String getSqlTemplate() {
		return sqlTemplate;
	}

}
